package solver

import (
	"gosudoku/set"
	"slices"
)

func verifyNaked(house House, cellNums []int) (ok bool, cands []int) {
	nakedCands := set.NewSet()
	for _, cellNum := range cellNums {
		nakedCands = nakedCands.Union(house.cells[cellNum].cands)
	}

	cands = nakedCands.GetList()
	ok = len(cands) == len(cellNums)
	return
}

func chooseNakedCellNums(house House, nakedCount int) []int {
	cellNums := []int{}
	for cellNum, cell := range house.cells {
		if cell.solved() || cell.cands.Count() > nakedCount {
			continue
		}
		cellNums = append(cellNums, cellNum)
	}
	return cellNums
}

func clearupNakedHouse(house House, cellNums []int, cands []int) (used bool) {
	for i, cell := range house.cells {
		if cell.solved() || slices.Contains(cellNums, i) {
			continue
		}
		for _, cand := range cands {
			if cell.removeCand(cand) {
				used = true
			}
		}
	}
	return
}

func (g *Grid) nakedHouse(house House, nakedCount int) (used bool) {
	cellNums := chooseNakedCellNums(house, nakedCount)
	subsets := combine(cellNums, nakedCount)
	for _, subset := range subsets {
		naked, cands := verifyNaked(house, subset)
		if !naked {
			continue
		}
		if clearupNakedHouse(house, subset, cands) {
			logNakedHidden("Naked", house, subset, cands)
			used = true
			return
		}
	}
	return
}

func (g *Grid) NakedPairHouse(house House) (used bool) {
	return g.nakedHouse(house, 2)
}

func (g *Grid) NakedPair() (used bool) {
	return g.doStrategy(g.NakedPairHouse)
}

func (g *Grid) NakedTripleHouse(house House) (used bool) {
	return g.nakedHouse(house, 3)
}

func (g *Grid) NakedTriple() (used bool) {
	return g.doStrategy(g.NakedTripleHouse)
}

func (g *Grid) NakedQuadrupleHouse(house House) (used bool) {
	return g.nakedHouse(house, 4)
}

func (g *Grid) NakedQuadruple() (used bool) {
	return g.doStrategy(g.NakedQuadrupleHouse)
}
